package server;

import java.awt.EventQueue;
import java.awt.Font;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Security;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import sameClasses.User;


public class Adminconsole extends JFrame {


  private static final long serialVersionUID = 1L;
  private JPanel contentPane;
  private JPasswordField oldpasswordField;
  private JPasswordField newpasswordField;
  private JPasswordField repeatpasswordField;
  protected Vector<char[]> serverConfig;
  protected JPasswordField masterpwField;
  protected JTextField adminusernameField;
  protected JPasswordField adminpwField;
  protected JTextField portField;
  protected Server theServer;
  private User admin;
  private JTextField FSadminusernameField;
  private JPasswordField FSadminpasswordField;
  private JPasswordField FSmasterpasswordField;
  private JTextField FSport;
  private JPasswordField FSrepeatadminpasswordField;
  private JPasswordField FSrepeatmasterpasswordField;
  private JPasswordField keystorepwField;
  private String keystorefile;
  private byte[] masterpwsalt;
  private byte[] adminpwsalt;
  private JTextField ADDuserUsernameField;
  private JPasswordField ADDuserPasswordField;
  private JPasswordField ADDuserRepeatpasswordField;
  private String keystorepw;
  private File datafile;
  private JButton btnStopServer;
  protected JPanel userPane;

  /**
   * Launch the application.
   */
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override
      public void run() {
        try {
          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
          Adminconsole frame = new Adminconsole();
          frame.setVisible(true);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    });
  }

  /**
   * Create the frame.
   */
  public Adminconsole() {
	Security.addProvider(new BouncyCastleProvider());
    setTitle("ENS administrators console");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 700, 483);
    load();
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);
    
    final JTabbedPane myTabbedPane = new JTabbedPane(SwingConstants.LEFT);
    myTabbedPane.setBounds(0, 0, 692, 453);
    contentPane.add(myTabbedPane);
    
    final JPanel panel = new JPanel();
    panel.setLayout(null);
    myTabbedPane.addTab("First start", null, panel, null);
    
    JLabel label = new JLabel("Administrator-Username:");
    label.setHorizontalAlignment(SwingConstants.RIGHT);
    label.setBounds(14, 255, 120, 14);
    panel.add(label);
    
    JLabel lblAdministratorLoginCredentials_1 = new JLabel("Administrator Login Credentials. Choose them wisely!");
    lblAdministratorLoginCredentials_1.setHorizontalAlignment(SwingConstants.CENTER);
    lblAdministratorLoginCredentials_1.setFont(new Font("Tahoma", Font.PLAIN, 16));
    lblAdministratorLoginCredentials_1.setBounds(0, 224, 576, 20);
    panel.add(lblAdministratorLoginCredentials_1);
    
    final JButton FSstopServerButton = new JButton("Stop server");
    final JButton button = new JButton("Start server");
    button.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        // create the administrator-user-object
        admin = new User(FSadminusernameField.getText());
        serverConfig = new Vector<char[]>();
        serverConfig.add(FSadminusernameField.getText().toCharArray());
        serverConfig.add(FSport.getText().toCharArray());
        keystorepw = String.copyValueOf(keystorepwField.getPassword());
        store();
        theServer = new Server(admin, datafile, FSmasterpasswordField.getPassword(), Integer.parseInt(FSport.getText()), keystorefile, keystorepw);
        userPane = theServer.getPluginManager().gui();
        myTabbedPane.addTab("Users", null, userPane, null);
        button.setEnabled(false);
        FSstopServerButton.setEnabled(true);
      }
    });
    button.setBounds(145, 360, 120, 23);
    panel.add(button);
    
    FSadminusernameField = new JTextField();
    FSadminusernameField.setColumns(10);
    FSadminusernameField.setBounds(145, 252, 120, 20);
    panel.add(FSadminusernameField);
    
    JLabel label_2 = new JLabel("Administrator-Password:");
    label_2.setHorizontalAlignment(SwingConstants.RIGHT);
    label_2.setBounds(8, 283, 126, 14);
    panel.add(label_2);
    
    MyDocumentListener fsadminpwDL = new MyDocumentListener();
    
    FSadminpasswordField = new JPasswordField();
    FSadminpasswordField.setBounds(145, 280, 120, 20);
    FSadminpasswordField.getDocument().addDocumentListener(fsadminpwDL);
    panel.add(FSadminpasswordField);
    
    JLabel label_3 = new JLabel("Masterpassword:");
    label_3.setToolTipText("");
    label_3.setHorizontalAlignment(SwingConstants.RIGHT);
    label_3.setBounds(14, 311, 120, 14);
    panel.add(label_3);
    
    MyDocumentListener fsmasterpwDL = new MyDocumentListener();
    
    FSmasterpasswordField = new JPasswordField();
    FSmasterpasswordField.setBounds(145, 308, 120, 20);
    FSmasterpasswordField.getDocument().addDocumentListener(fsmasterpwDL);
    panel.add(FSmasterpasswordField);
    
    FSport = new JTextField();
    FSport.setColumns(10);
    FSport.setBounds(145, 336, 120, 20);
    panel.add(FSport);
    
    JTextArea textArea = new JTextArea();
    textArea.setText("Requirements for the masterpassword:\r\n- minimum length of 8 chars\r\n- minimum strength (choose 3 of these): \r\n  - big letter(s)\r\n  - small letter(s)\r\n  - number(s)\r\n  - symbol(s)");
    textArea.setLineWrap(true);
    textArea.setFont(new Font("Tahoma", Font.PLAIN, 11));
    textArea.setEnabled(false);
    textArea.setEditable(false);
    textArea.setBackground(SystemColor.menu);
    textArea.setBounds(295, 335, 201, 102);
    panel.add(textArea);
    
    JLabel label_4 = new JLabel("Server listens on port:");
    label_4.setHorizontalAlignment(SwingConstants.RIGHT);
    label_4.setBounds(21, 339, 115, 14);
    panel.add(label_4);
    
    FSrepeatadminpasswordField = new JPasswordField();
    FSrepeatadminpasswordField.setBounds(376, 280, 120, 20);
    panel.add(FSrepeatadminpasswordField);
    
    JLabel label_5 = new JLabel("Adminpw-Repeat:");
    label_5.setHorizontalAlignment(SwingConstants.RIGHT);
    label_5.setBounds(267, 283, 100, 14);
    panel.add(label_5);
    
    JLabel label_6 = new JLabel("Masterpw-Repeat:");
    label_6.setHorizontalAlignment(SwingConstants.RIGHT);
    label_6.setBounds(267, 311, 100, 14);
    panel.add(label_6);
    
    MyDocumentListener fsrepeatmasterDL = new MyDocumentListener();
    FSrepeatmasterpasswordField = new JPasswordField();
    FSrepeatmasterpasswordField.setBounds(376, 308, 120, 20);
    FSrepeatmasterpasswordField.getDocument().addDocumentListener(fsrepeatmasterDL);
    panel.add(FSrepeatmasterpasswordField);
    
    JLabel lblSslCertificateInitialization = new JLabel("SSL Certificate Initialization (used for tunneling your data)");
    lblSslCertificateInitialization.setHorizontalAlignment(SwingConstants.CENTER);
    lblSslCertificateInitialization.setFont(new Font("Tahoma", Font.PLAIN, 16));
    lblSslCertificateInitialization.setBounds(0, 11, 576, 20);
    panel.add(lblSslCertificateInitialization);
    
    JButton btnOpenCommandline = new JButton("Open commandline");
    btnOpenCommandline.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        // Execute command
        String command = "cmd /c start cmd /k keytool -genkey -keyalg RSA -alias selfsignedENSserver -keystore server.keystore -storepass "+String.copyValueOf(keystorepwField.getPassword())+" -validity 10000 -keysize 2048";
        try {
          Process child = Runtime.getRuntime().exec(command);
          // Get output stream to write from it
          //out.write(new String("keytool -genkey -keyalg RSA -alias selfsigned -keystore myKeystore.jks -storepass "+String.copyValueOf(keystorepwField.getPassword())+" -keysize 2048 /r/n").getBytes());
          //out.write("keytool -genkey -keyalg RSA -alias selfsigned -keystore myKeystore.jks -storepass password -keysize 2048 /r/n".getBytes());
        } catch (IOException e) {
          e.printStackTrace();
        }
        command = "cmd /c start cmd /k keytool -genkey -keyalg RSA -alias selfsignedENSserver -keystore android.keystore -storepass "+String.copyValueOf(keystorepwField.getPassword())+" -validity 10000 -storetype BKS -keysize 2048 -providerClass org.bouncycastle.jce.provider.BouncyCastleProvider";
        try {
          Process child = Runtime.getRuntime().exec(command);
          // Get output stream to write from it
          //out.write(new String("keytool -genkey -keyalg RSA -alias selfsigned -keystore myKeystore.jks -storepass "+String.copyValueOf(keystorepwField.getPassword())+" -keysize 2048 /r/n").getBytes());
          //out.write("keytool -genkey -keyalg RSA -alias selfsigned -keystore myKeystore.jks -storepass password -keysize 2048 /r/n".getBytes());
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    });
    btnOpenCommandline.setBounds(225, 76, 181, 23);
    panel.add(btnOpenCommandline);
    
    JTextPane txtpnDescrSSL = new JTextPane();
    txtpnDescrSSL.setEnabled(false);
    txtpnDescrSSL.setEditable(false);
    txtpnDescrSSL.setBackground(SystemColor.menu);
    txtpnDescrSSL.setText("1. Provide a passwort for your certificate-keystore. Min. 6 chars.\r\n2. Click on the \"Open commandline\" button. A commandline window should be opened and you get prompted to enter your data.\r\n3. Choose your previously created keystore.\r\n4. Extract the certificate containing the public key of your server.");
    txtpnDescrSSL.setBounds(14, 42, 201, 146);
    panel.add(txtpnDescrSSL);
    
    JButton btnChooseServercertificate = new JButton("Choose serverkeystore");
    btnChooseServercertificate.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        JFileChooser fc = new JFileChooser();
        fc.showOpenDialog(null);
        keystorefile = fc.getSelectedFile().getAbsolutePath();
      }
    });
    btnChooseServercertificate.setBounds(225, 130, 181, 23);
    panel.add(btnChooseServercertificate);
    
    keystorepwField = new JPasswordField();
    keystorepwField.setBounds(295, 43, 111, 20);
    panel.add(keystorepwField);
    
    JLabel lblKeystorepw = new JLabel("Keystore-PW:");
    lblKeystorepw.setBounds(225, 46, 67, 14);
    panel.add(lblKeystorepw);
    
    if(new File("serverconfig.cfg").exists()) {
      myTabbedPane.removeTabAt(0);
    }
    panel.add(lblKeystorepw);
    
    JButton btnExtractServercertificate = new JButton("Extract servercertificate");
    btnExtractServercertificate.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        String command = "cmd /c start cmd /k keytool -export -keystore server.keystore -alias selfsignedENSserver -file selfsignedENSserver.cer";
        try {
          Process child = Runtime.getRuntime().exec(command);
        } catch (IOException e1) {
          e1.printStackTrace();
        }
      }
    });
    btnExtractServercertificate.setBounds(225, 160, 181, 23);
    panel.add(btnExtractServercertificate);
    
    JButton FSchooseDataFileButton = new JButton("Choose datastore-file");
    FSchooseDataFileButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
            JFileChooser fc = new JFileChooser();
            fc.showOpenDialog(null);
            datafile = fc.getSelectedFile();
      }
    });
    FSchooseDataFileButton.setBounds(225, 190, 181, 23);
    panel.add(FSchooseDataFileButton);
    
    final JPanel serverPane = new JPanel();
    FSstopServerButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        if(theServer.getPluginManager().stopMe()) {
          theServer.exitServer();
          myTabbedPane.addTab("Serverconfiguration", null, serverPane, null);
          myTabbedPane.remove(userPane);
          myTabbedPane.remove(panel);
          button.setEnabled(true);
          FSstopServerButton.setEnabled(false);
        }
      }
    });
    FSstopServerButton.setEnabled(false);
    FSstopServerButton.setBounds(145, 387, 120, 23);
    panel.add(FSstopServerButton);
    
    myTabbedPane.addTab("Serverconfiguration", null, serverPane, null);
    serverPane.setLayout(null);
    
    JLabel lblAdministratorlogin = new JLabel("Administrator-Username:");
    lblAdministratorlogin.setHorizontalAlignment(SwingConstants.RIGHT);
    lblAdministratorlogin.setBounds(14, 45, 120, 14);
    serverPane.add(lblAdministratorlogin);
    
    JLabel lblAdministratorLoginCredentials = new JLabel("Administrator Login Credentials");
    lblAdministratorLoginCredentials.setFont(new Font("Tahoma", Font.PLAIN, 16));
    lblAdministratorLoginCredentials.setHorizontalAlignment(SwingConstants.CENTER);
    lblAdministratorLoginCredentials.setBounds(0, 11, 506, 20);
    serverPane.add(lblAdministratorLoginCredentials);
    
    final JTextField adminusernameFieldConfig = new JTextField();
    adminusernameFieldConfig.setBounds(145, 42, 120, 20);
    adminusernameFieldConfig.setColumns(10);
    serverPane.add(adminusernameFieldConfig);
    
    btnStopServer = new JButton("Stop server");
    
    final JButton btnSubmit = new JButton("Start server");
    btnSubmit.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        // save data to the serverconfig
        serverConfig = new Vector<char[]>();
        serverConfig.add(adminusernameFieldConfig.getText().toCharArray());
        serverConfig.add(portField.getText().toCharArray());
        // create the adminuserobject
        admin = new User(adminusernameFieldConfig.getText());
        store();
        theServer = new Server(admin, datafile, masterpwField.getPassword(), Integer.parseInt(portField.getText()), keystorefile, keystorepw);
        userPane = theServer.getPluginManager().gui();
        myTabbedPane.addTab("Users", null, userPane, null);
        btnSubmit.setEnabled(false);
        btnStopServer.setEnabled(true);
      }
    });
    btnSubmit.setBounds(145, 191, 120, 23);
    serverPane.add(btnSubmit);
    
    JLabel lblAdministratorpassword = new JLabel("Administrator-Password:");
    lblAdministratorpassword.setHorizontalAlignment(SwingConstants.RIGHT);
    lblAdministratorpassword.setBounds(8, 73, 126, 14);
    serverPane.add(lblAdministratorpassword);
    
    
    adminpwField = new JPasswordField();
    adminpwField.setBounds(145, 70, 120, 20);
    serverPane.add(adminpwField);
    
    JLabel lblMasterpassword = new JLabel("Masterpassword:");
    lblMasterpassword.setToolTipText("");
    lblMasterpassword.setHorizontalAlignment(SwingConstants.RIGHT);
    lblMasterpassword.setBounds(14, 101, 120, 14);
    serverPane.add(lblMasterpassword);
    
    masterpwField = new JPasswordField();
    masterpwField.setBounds(145, 98, 120, 20);
    serverPane.add(masterpwField);
    
    portField = new JTextField();
    portField.setBounds(145, 126, 120, 20);
    serverPane.add(portField);
    portField.setColumns(10);
    
    JLabel lblServerport = new JLabel("Server listens on port:");
    lblServerport.setHorizontalAlignment(SwingConstants.RIGHT);
    lblServerport.setBounds(21, 129, 115, 14);
    serverPane.add(lblServerport);
    
    JButton btnDatafile = new JButton("Choose datafile");
    btnDatafile.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        JFileChooser fc = new JFileChooser();
        fc.showOpenDialog(serverPane);
        datafile = fc.getSelectedFile();
        System.out.println(datafile.getAbsolutePath());
        }
      });
    btnDatafile.setBounds(145, 157, 120, 23);
    serverPane.add(btnDatafile);
    
    JButton btnCreateNewInstance = new JButton("Create new instance");
    btnCreateNewInstance.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        myTabbedPane.addTab("New server", null, panel, null);
        myTabbedPane.setSelectedComponent(panel);
        myTabbedPane.remove(serverPane);
      }
    });
    btnCreateNewInstance.setBounds(416, 381, 150, 23);
    serverPane.add(btnCreateNewInstance);

    btnStopServer.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        if(theServer.getPluginManager().stopMe()) {
          btnSubmit.setEnabled(true);
          btnStopServer.setEnabled(false);
          theServer.exitServer();
          myTabbedPane.remove(userPane);
        }
      }
    });
    btnStopServer.setBounds(275, 191, 120, 23);
    btnStopServer.setEnabled(false);
    serverPane.add(btnStopServer);
    
    /*
    JPanel masterpwPane = new JPanel();
    myTabbedPane.addTab("Masterpassword", null, masterpwPane, null);
    masterpwPane.setLayout(null);
    
    JLabel lblChangeTheMasterpassword = new JLabel("Change the masterpassword");
    lblChangeTheMasterpassword.setFont(new Font("Tahoma", Font.PLAIN, 12));
    lblChangeTheMasterpassword.setHorizontalAlignment(SwingConstants.CENTER);
    lblChangeTheMasterpassword.setBounds(0, 11, 476, 14);
    masterpwPane.add(lblChangeTheMasterpassword);
    
    JLabel lblOldMasterpassword = new JLabel("Old masterpassword:");
    lblOldMasterpassword.setHorizontalAlignment(SwingConstants.RIGHT);
    lblOldMasterpassword.setBounds(10, 36, 107, 14);
    masterpwPane.add(lblOldMasterpassword);
    
    oldpasswordField = new JPasswordField();
    oldpasswordField.setBounds(127, 33, 150, 20);
    masterpwPane.add(oldpasswordField);
    
    JLabel lblNewMasterpassword = new JLabel("New masterpassword:");
    lblNewMasterpassword.setHorizontalAlignment(SwingConstants.RIGHT);
    lblNewMasterpassword.setBounds(10, 61, 107, 14);
    masterpwPane.add(lblNewMasterpassword);
    
    JLabel lblRepeat = new JLabel("Repeat:");
    lblRepeat.setHorizontalAlignment(SwingConstants.RIGHT);
    lblRepeat.setBounds(10, 86, 107, 14);
    masterpwPane.add(lblRepeat);
    
    newpasswordField = new JPasswordField();
    newpasswordField.setBounds(127, 58, 150, 20);
    masterpwPane.add(newpasswordField);
    
    repeatpasswordField = new JPasswordField();
    repeatpasswordField.setBounds(127, 83, 150, 20);
    masterpwPane.add(repeatpasswordField);
    
    JButton btnChange = new JButton("Change");
    btnChange.setBounds(127, 114, 89, 23);
    masterpwPane.add(btnChange);
    */
  }
  
  private boolean store() {
    try {
      ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(new File("serverconfig.cfg")));
      os.writeObject(serverConfig);
      os.writeObject(datafile);
      os.writeObject(keystorefile);
      os.writeObject(keystorepw);
      os.flush();
      os.close();
    } catch (IOException e) {
      System.err.println(e.toString());
      return false;
    }
    System.out.println("Serverconfig saved to harddisk");
    return true;
  }

  private Vector<char[]> load() {
    try {
      ObjectInputStream is = new ObjectInputStream(new FileInputStream(new File("serverconfig.cfg")));
      Vector<char[]> ret = (Vector<char[]>) is.readObject();
      this.datafile = (File) is.readObject();
      System.out.println(this.datafile.exists());
      keystorefile = (String) is.readObject();
      keystorepw = (String) is.readObject();
      is.close();
      System.out.println("Serverconfig successfully loaded from serverconfig.cfg");
      return ret;
    } catch (ClassNotFoundException e) {
      System.err.println(e.toString());
    } catch (IOException e) {
      System.err.println(e.toString());
    }
    System.out.println("Serverconfig NOT loaded from serverconfig.cfg");
    return serverConfig;
  }
  
  class MyDocumentListener implements DocumentListener {

    private int count = 0;
    
    public int getCount() {
      return this.count;
    }
    
    @Override
    public void changedUpdate(DocumentEvent arg0) {
    }

    @Override
    public void insertUpdate(DocumentEvent arg0) {
      this.count++;
    }

    @Override
    public void removeUpdate(DocumentEvent arg0) {
      this.count--;
    }
  }
  
  protected static void errorPopup(String message) {
    final JFrame popup = new JFrame();
    popup.setTitle("An error occured!");
    final JPanel cont = new JPanel();
    popup.setBounds(300, 100, 600, 250);
    popup.getContentPane().setLayout(null);
    popup.setVisible(true);
    popup.setContentPane(cont);
    cont.setLayout(null);
    JLabel lblerror = new JLabel(message);
    lblerror.setBounds(20, 10, 300, 46);
    lblerror.setHorizontalAlignment(SwingConstants.RIGHT);
    lblerror.setVisible(true);
    cont.add(lblerror);

    JButton btnOK = new JButton("OK");
    btnOK.setBounds(150, 150, 50, 23);
    btnOK.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        popup.dispose();
      }
    });
    btnOK.setVisible(true);
    cont.add(btnOK);
    popup.setContentPane(cont);
  }
}
